﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using ResourceBlender.Core;

namespace ResourceBlender.Core {
    /// <summary>
    /// WordNet support adapted from Translate.Net - http://code.google.com/p/translateclient/
    /// </summary>
    public class WordNet {
        /// <summary>
        /// Looks up a phrase.
        /// </summary>
        /// <param name="phrase">The phrase to lookup.</param>
        /// <returns>A collection of definitions for the phrase</returns>
        public static DefinitionCollection Lookup(string phrase) {
            if(phrase.Contains(" ")) {
                throw new ResourceBlenderException("Only one-word definitions are supported");
            }
            if(phrase.Trim().Length == 0) {
                return null;
            }
            string serviceUrl;
            bool useCache = false;
            if(useCache) {
                serviceUrl = "http://www.google.com/search?q=cache:wordnetweb.princeton.edu/perl/webwn?s=" + System.Uri.EscapeDataString(phrase); 
            } else {
                serviceUrl = "http://wordnetweb.princeton.edu/perl/webwn?s=" + System.Uri.EscapeDataString(phrase);
            }
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(serviceUrl);
            req.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;.NET CLR 2.0.50727)";
            req.KeepAlive = true;
            req.Method = "GET";
            WebResponse webResponse = req.GetResponse();
            StreamReader resReader = new StreamReader(webResponse.GetResponseStream());
            string response = resReader.ReadToEnd();
            //Console.WriteLine(response);

            if(response.Contains("<h3>Your search did not return any results.</h3>")) {
                throw new ResourceBlenderException("No definitions found");
            }
            if(response.Contains("<h3>Sorry(?) your search can only contain letters(?)")) {
                throw new ResourceBlenderException("Search can only contain letters");
            }

            List<WordDefinition> results = new List<WordDefinition>();
            IEnumerable<string> nodes = StringParser.ParseItemsList("<h3>", "</ul>", response);
            string nodename,
                   translation;
            //WordDefinition def = new WordDefinition();

            foreach(string node in nodes) {
                WordDefinition def = new WordDefinition();
                nodename = StringParser.ExtractLeft("</h3>", node);
                def.DefinitionType = nodename;
                results.Add(def);

                IEnumerable<string> subnodes = StringParser.ParseItemsList("<li>", "</li>", node);
                foreach(string subnode in subnodes) {
                    translation = StringParser.RemoveAll("<", ">", subnode);
                    translation = StringParser.ExtractRight(")", translation);
                    def.Meanings.Add(translation);
                }
            }
            results.Sort();
            DefinitionCollection resultDefiniton = new DefinitionCollection() {
                DefinedWord = phrase,
                ServiceUrl = serviceUrl,
                Definitions = results
            };
            return resultDefiniton;
        }

        /// <summary>
        /// Determines whether WordNet supports a language. Only English is supported.
        /// </summary>
        /// <param name="languageCode">The language code.</param>
        /// <returns>
        /// 	<c>true</c> if the language is supported by WordNet, otherwise <c>false</c>.
        /// </returns>
        public static bool IsLanguageSupported(string languageCode) {
            return languageCode != null && languageCode.StartsWith("en");
        }

        /// <summary>
        /// Returns dummy data without querying the WordNet service.
        /// </summary>
        /// <returns>Dummy data without querying the WordNet service.</returns>
        public static DefinitionCollection GetDummyData() {
            DefinitionCollection def = new DefinitionCollection() { 
                DefinedWord = "Save", ServiceUrl = "woot.com" 
            };
            WordDefinition def1 = new WordDefinition() {
                DefinitionType = "Noun"
            };
            def1.Meanings.Add("save ((sports) the act of preventing the opposition from scoring) \"the goalie made a brilliant save\"; \"the relief pitcher got credit for a save\"");
            def.Definitions.Add(def1);

            WordDefinition def3 = new WordDefinition() {
                DefinitionType = "Verb"
            };
            def3.Meanings.AddRange(new string[] {
	            "salvage, salve, relieve, save (save from ruin, destruction, or harm)",
	            "save, preserve (to keep up and reserve for personal or special use) She saved the old family photographs in a drawer",
	            "save, carry through, pull through, bring through (bring into safety) We pulled through most of the victims of the bomb attack",
	            "save (spend less; buy at a reduced price)",
	            "save, lay aside, save up (accumulate money for future use) He saves half his salary",
	            "save, make unnecessary (make unnecessary an expenditure or effort) This will save money; I'll save you the trouble; This will save you a lot of time",
	            "deliver, redeem, save (save from sins)",
	            "spare, save (refrain from harming)",
	            "save, economize, economise (spend sparingly, avoid the waste of) This move will save money; The less fortunate will have to economize now",
	            "keep open, hold open, keep, save (retain rights to) keep my job for me while I give birth; keep my seat, please; keep open the possibility of a merger",
	            "write, save (record data on a computer) boot-up instructions are written on the hard disk"});
            def.Definitions.Add(def3);

            WordDefinition def2 = new WordDefinition() {
                DefinitionType = "Noun"
            };
            def2.Meanings.Add("save ((sports) the act of preventing the opposition from scoring) the goalie made a brilliant save; the relief pitcher got credit for a save");
            def.Definitions.Add(def2);

            WordDefinition def4 = new WordDefinition() {
                DefinitionType = "Verb"
            };
            def4.Meanings.AddRange(new string[] {
	            "salvage, salve, relieve, save (save from ruin, destruction, or harm)",
                "save, preserve (to keep up and reserve for personal or special use) She saved the old family photographs in a drawer",
                "save, carry through, pull through, bring through (bring into safety) We pulled through most of the victims of the bomb attack",
                "save (spend less; buy at a reduced price)",
                "save, lay aside, save up (accumulate money for future use) He saves half his salary",
                "save, make unnecessary (make unnecessary an expenditure or effort) This will save money; I'll save you the trouble; This will save you a lot of time",
                "deliver, redeem, save (save from sins)",
                "spare, save (refrain from harming)",
                "save, economize, economise (spend sparingly, avoid the waste of) This move will save money; The less fortunate will have to economize now",
                "keep open, hold open, keep, save (retain rights to) keep my job for me while I give birth; keep my seat, please; keep open the possibility of a merger",
                "write, save (record data on a computer) boot-up instructions are written on the hard disk"});
            def.Definitions.Add(def4);
            def.Definitions.Sort();
            return def;
        }
    }
}
